<template>
  <view>
    <u-upload
        :fileList="fileList"
        @beforeRead="beforeRead"
        @afterRead="afterRead"
        @delete="deletePic"
        :capture="capture"
        multiple
        :maxCount="maxCount"
    ></u-upload>
    <!-- 上传提示 -->
    <slot name="tip" v-if="showTip">
      <view class="el-upload__tip" slot="tip">
        请上传
        <template v-if="fileSize"> 大小不超过
          <text style="color: #f56c6c">{{ fileSize }}MB</text>
        </template>
        <template v-if="fileType"> 格式为
          <text style="color: #f56c6c">{{ fileType.join('/') }}</text>
        </template>
        的文件
      </view>
    </slot>
    <view style="position: absolute;top: -999999px;">
      <view>
        <!--        <canvas style="width: 1000px;height: 1000px;" canvas-id="myCanvas"></canvas>-->
        <canvas :style="{width: canvasWidth + 'px', height: canvasHeight + 'px'}" canvas-id="imageCanvas"
                id="imageCanvas"></canvas>
      </view>
    </view>
  </view>
</template>

<script>
import config from '@/config'
import {getToken} from '@/utils/auth'
import {uploadImg} from '@/api/common'

export default {
  name: "image-upload",
  props: {
    value: {
      type: [String, Array],
      default: ''
    },
    //最大上传数量
    maxCount: {
      type: Number,
      default: 2
    },
    //是否显示提示
    isShowTip: {
      type: Boolean,
      default: true
    },
    // 文件类型, 例如['png', 'jpg', 'jpeg']
    fileType: {
      type: Array,
      default: () => {
        return ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']
      }
    },
    //文件大小
    fileSize: {
      type: Number,
      default: 10
    },
    // 上传参数
    options: {
      type: Object,
      default: () => {
        return {
          name: 'fileName',
          url: 'url',
        }
      }
    },
    // 是否使用相机
    capture: {
      type: [String, Array],
      default: ['album', 'camera']
    },
    // 是否显示水印
    showWaterMark: {
      type: Boolean,
      default: false
    },
    waterMarkText: {
      type: String,
      default: ''
    },

  },
  data() {
    return {
      fileList: [],
      uploadList: [],
      list: [],
      baseUrl: 'http://localhost:8080',
      action: `${config.baseUrl}/front/common/upload`,
      canvasWidth: 0,
      canvasHeight: 0,
      watermarkStatus: true,
    }
  },
  computed: {
    // 是否显示提示
    showTip() {
      return this.isShowTip && (this.fileType || this.fileSize)
    },
    // 类型判断
    valueType() {
      return Array.isArray(this.value) ? 'array' : 'string'
    }
  },
  watch: {
    value: {
      handler(val) {
        if (val) {
          console.log('value', val)
          // 首先将值转为数组
          const list = Array.isArray(val) ? val : this.value.split(',')
          // 然后将数组转为对象数组
          this.list = list.map(item => {
            if (typeof item === 'string') {
              if (item.indexOf(this.baseUrl) === -1) {
                item = {item, url: item}
              } else {
                item = {name: item, url: item}
              }
            }
            return item
          })
          this.fileList = this.list.map(item => {
            return {
              name: item.name,
              url: item.url,
              status: 'finished',
              message: '上传成功'
            }
          })
        } else {
          this.list = []
          this.fileList = []
          return []
        }
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    // 新增图片
    async afterRead(event) {
      console.log('afterRead', event)
      // 校验文件类型
      if (this.fileType.length) {
        let fileExtension = ''
        for (let i = 0; i < event.file.length; i++) {
          // 获取文件后缀
          fileExtension = event.file[i].url.split('.').pop().toLowerCase()
          console.log('fileExtension', fileExtension, this.fileType)
          // 判断文件后缀是否在允许的类型中
          if (this.fileType.indexOf(fileExtension) === -1) {
            // 文件类型不正确，不允许上传
            uni.showToast({
              title: '文件类型不正确',
              icon: 'none'
            })
            return false
          }
          // 判断文件大小是否超出限制
          if (event.file[i].size > this.fileSize * 1024 * 1024) {
            // 文件大小超出限制，不允许上传
            uni.showToast({
              title: '文件大小超出限制',
              icon: 'none'
            })
            return false
          }
        }
      }
      // 检验文件数量
      if (this.maxCount && this.fileList.length + event.file.length > this.maxCount) {
        uni.showToast({
          title: '最多只能上传' + this.maxCount + '张图片',
          icon: 'none'
        })
        return false
      }
      // 当设置 multiple 为 true 时, file 为数组格式，否则为对象格式
      let lists = [].concat(event.file)
      let fileListLen = this[`fileList${event.name}`].length
      console.log('fileListLen', fileListLen)
      lists.map((item) => {
        this[`fileList${event.name}`].push({
          ...item,
          status: 'uploading',
          message: '上传中'
        })
      })
      // 上传图片添加水印,多张图片添加水印
      if (this.showWaterMark && this.watermarkStatus) {
        //YYYY-MM-DD HH:mm:ss
        let text = this.$moment().format('YYYY年MM月DD日 HH:mm:ss')
        console.log('text', text)
        let waterMark = await this.generateWaterMark(lists, this.waterMarkText)
        // uni.previewImage({
        //   urls: lists.map(item => item.url),
        // })
        // return

        console.log('水印处理完了')
      }
      console.log('开始遍历上传图片', lists)
      for (let i = 0; i < lists.length; i++) {
        console.log('开始上传图片', lists[i])
        const result = await this.uploadFilePromise(lists[i].url, event)
        console.log('上传图片结果', result)
        let item = this[`fileList${event.name}`][fileListLen]
        this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
          status: 'success',
          message: '',
          url: result
        }))
        fileListLen++
      }

      console.log('this.fileList', this.fileList)
    },
    async uploadFilePromise(url, event) {
      console.log('开始调用上传接口', url)
      let result = await uploadImg(url)
      console.log('上传接口返回结果', result)
      this.uploadList.push({name: result[this.options.name], url: result[this.options.url]})
      this.list = this.list.concat(this.uploadList)
      this.uploadList = []
      console.log('处理图片值类型', this.valueType)
      if (this.valueType === 'array') {
        this.$emit('input', this.objectToList(this.list))
      } else {
        console.log('this.list', this.list)
        this.$emit('input', this.listToString(this.list))
      }
      this.$emit('change', event, this.list)
      return result.url
    },
    // 删除图片
    deletePic(event) {
      this[`fileList${event.name}`].splice(event.index, 1)
      this.list.splice(event.index, 1)
      if (this.valueType === 'array') {
        this.$emit('input', this.objectToList(this.list))
      } else {
        this.$emit('input', this.listToString(this.list))
      }
      this.$emit('change', event, this.list)
    },
    //数组转字符串
    listToString(list, separator) {
      let strs = '';
      separator = separator || ',';
      for (let i in list) {
        if (list[i].url) {
          strs += list[i].url + separator;
        }
      }
      return strs != '' ? strs.substr(0, strs.length - 1) : ''
    },
    // 对象数组转成字符串数组
    objectToList(obj) {
      let list = []
      for (let i in obj) {
        list.push(obj[i].url)
      }
      return list
    },
    //生成图片水印，返回图片临时路径
    generateWaterMark(imgList, text) {
      console.log('生成图片水印前期')
      return new Promise(async (resolve, reject) => {
        let list = []
        await imgList.forEach(async (item) => {
          let img = await this.getImageInfo(item.url);
          let waterMark = await this.drawWaterMark(img, text)
          console.log('waterMark:before', waterMark)
          item.url = waterMark

          list.push(item)
          if (list.length === imgList.length) {
            console.log('imgList:after')
            resolve(list)
          }
        })

      })
    },
    // 绘制图片水印
    drawWaterMark(img, text) {
      console.log('初始化画布')

      // 找到较长的一边
      const maxSide = Math.max(img.width, img.height);
      let radio = 1
      if(maxSide > 350){
        radio = 350 / maxSide
      }

      let imageWidth = Math.round(img.width * radio)
      let imageHeight = Math.round(img.height * radio)


      this.canvasWidth = imageWidth
      this.canvasHeight = imageHeight
      // 创建画布
      let context = uni.createCanvasContext('imageCanvas', this)
      // 设置画布背景、宽高
      context.setFillStyle('#fff')
      context.fillRect(0, 0, imageWidth, imageHeight)
      // 加载图片
      context.drawImage(img.path, 0, 0, imageWidth, imageHeight)
      // 设置字体、字体大小、颜色、加粗
      context.setFontSize(imageWidth / 25)
      context.setFillStyle('#fff')

      // 右下角

      // 绘制文字
      context.setTextAlign('right')
      context.setTextBaseline('bottom')
      context.fillText(text, imageWidth - 10, imageHeight - 30)
      // 绘制时间
      context.setTextAlign('right')
      context.setTextBaseline('bottom')
      context.fillText(this.$moment().format('YYYY年MM月DD日 HH:mm'), imageWidth - 10, imageHeight - 10)


      // 保存图片
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          context.draw(false, () => {
            uni.canvasToTempFilePath({
              canvasId: 'imageCanvas',
              success: (res) => {
                resolve(res.tempFilePath)
              },
              fail: (err) => {
                reject(err)
              }
            }, this)
          })
        }, 1000)

      })
    },
    //获取图片
    getImageInfo(imgSrc) {
      return new Promise((resolve, reject) => {
        uni.getImageInfo({
          src: imgSrc,
          success: (image) => {
            resolve(image);
            console.log('获取图片成功', image)
          },
          fail: (err) => {
            reject(err);
            console.log('获取图片失败', err)
          }
        });
      });
    },

  }
}
</script>

<style scoped lang="scss">

</style>
